/***********************************************************************************************************************
 * ############################################# Application AdewebLite #############################################
 * AdewebLite Android est une application permettant de consulter des emplois du temps fournis par l'université UHP
 * avec ou sans connexion internet (informations gardées en mémoire à chaque synchronisation). Et utilisant la web
 * API ADE pour collecter les données.
 * @author Andrianjafintrimo Victor, Zanette Sébastien
 * 
 * Basée sur l'application du même nom, utilisant le flux RSS (données à traiter), de :
 * @author Schnell Michaël, Zanette Sébastien
 * **********************************************************************************************************************
 */

package ade.screen;

import greendroid.app.GDActivity;
import greendroid.widget.ActionBarItem;
import greendroid.widget.ActionBarItem.Type;
import greendroid.widget.LoaderActionBarItem;
import ade.database.Database;
import ade.exception.AAAException;
import ade.main.R;
import ade.schedule.Lesson;
import ade.schedule.Lessons;
import ade.schedule.ListLessonAdapter;
import ade.schedule.Schedule;
import ade.schedule.UpdateListener;
import ade.schedule.UpdateManager;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.MenuItem;
import android.view.View;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;

/**
 * View displaying the information about a schedule.
 * 
 * @author		Schnell Michaël, Zanette Sébastien
 */
public class ScheduleScreen extends GDActivity implements UpdateListener {

	/**
	 * Graphical component displaying the lessons of this schedule.
	 */
	private ListView liste ;

	/**
	 * Name of the displayed schedule.
	 */
	private String nameDisplayedSchedule ;

	/**
	 * Currently selected lesson.
	 */
	private Lesson currentLesson ;

	/**
	 * Dialog displayed when the containing schedule is being updated.
	 */
	protected ProgressDialog updateDialog ;

	private boolean doNotLoad;

	/**
	 * Id of the refresh item in the action bar.
	 */
	private static final int ITEM_REFRESH = 0 ;

	/**
	 * Id of the edit item in the action bar.
	 */
	private static final int ITEM_EDIT    = 1 ;

	/**
	 * Initializes this view.
         * 
         * @param savedInstanceState 
         */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState) ;
		Bundle bundle = this.getIntent().getExtras() ;
		this.nameDisplayedSchedule = bundle.getString("ade.screen.nameCurrentSchedule") ;
		this.setTitle(this.nameDisplayedSchedule) ;
		setActionBarContentView(R.layout.schedule_screen) ;
		this.initActionBar() ;
		this.doNotLoad = false ;
	}// onCreate(Bundle)

	/**
	 * Adds this view to the listener list of the {@code UpdateManager}.
	 */
	@Override
	protected void onStart() {
		super.onStart() ;
		if (!this.doNotLoad) {
			UpdateManager um = UpdateManager.getInstance() ;
			um.addListener(this) ;
			int status = um.getScheduleStatus(this.nameDisplayedSchedule) ;
			if (status != UpdateManager.STATUS_UPDATING) {
				this.createLessonList() ;
			} else {
				this.onUpdate(this.nameDisplayedSchedule, status) ;
			}// if
		}// if
	}// onStart()

	/**
	 * Removes this view from the listener list of the {@code UpdateManager}.
	 */
	@Override
	protected void onStop() {
		super.onStop() ;
		UpdateManager.getInstance().removeListener(this) ;
	}// onStop()

	/**
	 * Check if the displayed schedule still exists and return to the previous 
	 * screen if it is not the case.
	 */
	@Override
	protected void onRestart() {
		super.onRestart() ;
		Database db = new Database() ;
		try {
			db.getScheduleWithName(this.nameDisplayedSchedule) ;
		} catch (AAAException e) {
			// L'edt n'existe pas
			this.doNotLoad = true ;
			this.onBackPressed() ;
		}// try
	}// onRestart()

	/**
	 * Initializes the action bar of this view.
	 */
	private void initActionBar() {
		this.addActionBarItem(Type.Refresh, ScheduleScreen.ITEM_REFRESH) ;
		this.addActionBarItem(Type.Edit, ScheduleScreen.ITEM_EDIT) ;
	}// initActionBar()

         /**
         * Vérifie si l'appareil est connecté à Internet
         * @return vrai si l'appareil est connecté à Internet, faux sinon
         */
        public boolean isNetworkAvailable() {
        ConnectivityManager connectivityManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        return activeNetworkInfo != null;
    }
        
	/**
	 * Handles the clicks on the action bar items.
	 */
	@Override
	public boolean onHandleActionBarItemClick(ActionBarItem item, int position) {
		switch (item.getItemId()) {
		case ITEM_REFRESH :
                        if(this.isNetworkAvailable()){
                            this.updateSchedule() ;
                        }else{
                           Toast.makeText(this,"Synchronisation impossible", Toast.LENGTH_LONG).show() ; 
                           LoaderActionBarItem refreshItem = (LoaderActionBarItem) item;
                           refreshItem.setLoading(false);
                        }
			break ;

		case ITEM_EDIT :
			Intent intent = new Intent(ScheduleScreen.this, EditScheduleScreen.class) ;
			intent.putExtra("ade.screen.nameCurrentSchedule", this.nameDisplayedSchedule) ;
			this.startActivity(intent) ;
			break ;
			
		default :
			return super.onHandleActionBarItemClick(item, position) ;
		}// switch

		return true ;
	}// onHandleActionBarItemClick(ActionBarItem, int)

	/**
	 * Inflates the menu after a long click on a list item.
	 * 
	 * @param	menu  
	 * 			the context menu that is being built 
	 * 
	 * @param	v
	 * 			the view for which the context menu is being built 
	 * 
	 * @param	menuInfo
	 * 			extra information about the item for which the context menu should
	 * 			be shown
	 */
	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo) {
		super.onCreateContextMenu(menu, v, menuInfo);
		this.getMenuInflater().inflate(R.layout.context_menu_lesson, menu) ;
		AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo ;
		Adapter aa = ((ListView) v).getAdapter() ;
		this.currentLesson = (Lesson) aa.getItem(info.position) ;
		menu.setHeaderTitle(this.currentLesson.getTitle()) ;
	}// onCreateContextMenu(ContextMenu, View, ContextMenuInfo)

	/**
	 * Handles the click on the contextual menu of the lessons.
	 * 
	 * @param item the context menu item that was selected
         * 			
         * @return  
	 */
	@Override
	public boolean onContextItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.mark :
			this.mark() ;
			break ;
			
		case R.id.info :
			this.detailsDisplay() ;
			break ;

		default :
			return super.onContextItemSelected(item) ;
		}// switch
		return true ;
	}// onContextItemSelected(MenuItem)

	/**
	 * Inflates a new view containing a form used to mark a lesson.
	 */
	private void mark() {
		String[] items = {"normal", "important", "examen"} ;
		int checkItem = this.currentLesson.getType() ;
		AlertDialog.Builder builder = new AlertDialog.Builder(this) ;
		builder.setSingleChoiceItems(items, checkItem, new MarkLessonListener(this.currentLesson)) ;
		builder.setTitle("Marquer ce cours") ;
		builder.setIcon(RESULT_OK) ;
		builder.create().show() ;
	}// mark()

	/**
	 * Moves the user to the {@code LessonScreen}.
	 * 
	 * @see		LessonScreen
	 */
	public void detailsDisplay() {
		Intent intent = new Intent(ScheduleScreen.this, LessonScreen.class) ;
		intent.putExtra("ade.screen.lesson", this.currentLesson) ;
		intent.putExtra("ade.screen.nameCurrentSchedule", this.nameDisplayedSchedule) ;
		ScheduleScreen.this.startActivity(intent) ;
	}// detailsDisplay()

	/**
	 * Retrieves informations of the schedules and displays them
	 * on the screen.
	 */
	public void createLessonList () {            
		try {
			Database db = new Database() ;
			Schedule s = db.getScheduleWithName(this.nameDisplayedSchedule) ;  
			s.build(db) ;	
			Lessons lessons = s.getLessons() ;
		
			if (this.liste == null) {
				this.liste = (ListView) this.findViewById(R.id.listLesson) ;
				this.liste.setEmptyView(findViewById(R.id.empty)) ;
				ListLessonAdapter adapter = new ListLessonAdapter(this, lessons) ;
				this.liste.setAdapter(adapter) ;
				this.liste.setOnItemClickListener(new LessonListener(this.nameDisplayedSchedule, 
						adapter)) ;
				registerForContextMenu(this.liste) ;
			} else {
				ListLessonAdapter adapter = (ListLessonAdapter) this.liste.getAdapter() ;
				adapter.setLesson(lessons) ;
			}// if
		} catch (AAAException e) {
			Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show() ;
		}// try
	}// createLessonList()

	/**
	 * Adds this schedule to the update queue.
	 */
	public void updateSchedule() {
		UpdateManager.getInstance().addQueue(this.nameDisplayedSchedule) ;
	}// updateSchedule()

	/**
	 * Used to display a dialog when the containing schedule is being updated.
	 */
	public void onUpdate(Object... args) {
		try {
			String scheduleName = (String)  args[0] ;
			int scheduleState   = (Integer) args[1] ;
			if (scheduleName.equals(this.nameDisplayedSchedule)) {
				if (scheduleState == UpdateManager.STATUS_UPDATING) {
					if (this.updateDialog == null) {
						this.updateDialog = ProgressDialog.show(this, 
								"Chargement", "Mise à jour en cours ...", 
								true, true, new UpdateCancelListener(this)) ;
						LoaderActionBarItem refreshItem = 
								(LoaderActionBarItem) this.getActionBar().getItem(ITEM_REFRESH) ;
						refreshItem.setLoading(true) ;
					}// if
				} else {
					if (this.updateDialog != null) {
						this.updateDialog.dismiss() ;
						LoaderActionBarItem refreshItem = 
								(LoaderActionBarItem) this.getActionBar().getItem(ITEM_REFRESH) ;
						refreshItem.setLoading(false) ;
						this.updateDialog = null ;
						this.createLessonList() ;
					}// if
				}// if
			}// if
//			String newName = (String) args[3] ;
//			this.nameDisplayedSchedule = newName ;
//			this.getIntent().getExtras().putString("ade.screen.nameCurrentSchedule", this.nameDisplayedSchedule) ;
		} catch (Exception e) {/* Nothing to be done. */}//try
	}// onUpdate(Object...)

	/**
	 * OnCancelListener for the cancel action when the user wants to leave this 
	 * view while the schedule is being updated.
	 * 
	 * @author	Schnell Michaël, Zanette Sébastien
	 */
	class UpdateCancelListener implements OnCancelListener {
		
		/**
		 * View containing the component attached to this listener.
		 */
		protected ScheduleScreen container ;

		/**
		 * Sole constructor. 
		 * 
		 * @param 	container
		 * 			View containing the component attached to this listener
		 */
		public UpdateCancelListener(ScheduleScreen container) {
			super();
			this.container = container ;
		}// UpdateCancelListener(ScheduleScreen)

		/**
		 * Handles the cancel action.
		 * 
		 * @param	actualView
		 * 			view of the component who has received a click event
		 */
		public void onCancel(DialogInterface dialog) {
			dialog.dismiss() ;
			this.container.onBackPressed() ;
		}// onCancel(DialogInterface)
		
	}// class UpdateCancelListener
	
	/**
	 * OnClickListener for the mark action when the user wants to mark a 
	 * lesson from this schedule.
	 * 
	 * @author	Schnell Michaël, Zanette Sébastien
	 */
	class MarkLessonListener implements DialogInterface.OnClickListener {
		
		/**
		 * The modified lesson.
		 */
		protected Lesson lesson ;
		
		/**
		 * Sole constructor.
		 * 
		 * @param 	lesson
		 * 			the lesson which is being modified.
		 */
		public MarkLessonListener(Lesson lesson) {
			super() ;
			this.lesson = lesson ;
		}// MarkLessonListener(Lesson)

		/**
		 * Handles the click.
		 * 
		 * @param	dialog
		 * 			the dialog that received the click
		 * 
		 * @param	item
		 * 			the button that was clicked or the position of the item clicked.  
		 */
		public void onClick(DialogInterface dialog, int item) {
			if (item != this.lesson.getType()) {
				this.lesson.setType(item) ;
				Database db = new Database() ;
				db.updateLesson(this.lesson.getLessonId(), 
						this.lesson.getSchedule(),
						this.lesson) ;
			}// if
			dialog.dismiss() ;
		}// onClick(DialogInterface, int)
		
	}// class MarkLessonListener
	
	/**
	 * OnItemClickListener which handles the clicks on the lesson list.
	 * 
	 * @author	Schnell Michaël, Zanette Sébastien
	 */
	class LessonListener implements AdapterView.OnItemClickListener {
		
		/**
		 * Name of the displayed schedule.
		 */
		protected String nameSchedule ;
		
		/**
		 * Adapter for the list attached to this listener.
		 */
		protected ListLessonAdapter adapter ;
		
		/**
		 * Sole constructor.
		 * 
		 * @param 	nameSchedule
		 * 			name of the displayed schedule
		 * 
		 * @param	adapter
		 * 			adapter for the list attached to this listener
		 */
		public LessonListener(String nameSchedule, ListLessonAdapter adapter) {
			super();
			this.nameSchedule = nameSchedule ;
			this.adapter = adapter ;
		}// LessonListener(String, ListLessonAdapter)
		
		/**
		 * Handles the click on a lesson from this schedule.
		 */
		public void onItemClick(AdapterView<?> a, View v, int position, long id) {
			Intent intent = new Intent(ScheduleScreen.this, LessonScreen.class) ;
			Lesson lesson =  (Lesson) this.adapter.getItem(position) ;
			intent.putExtra("ade.screen.lesson", lesson) ;
			intent.putExtra("ade.screen.nameCurrentSchedule", this.nameSchedule) ;
			ScheduleScreen.this.startActivity(intent) ;
		}// onItemClick(AdapterView<?>, View, int, long)
		
	}// class LessonListener

}// class ScheduleScreen